package com.bauer.framework.autumn.web.mapping;

import com.bauer.framework.autumn.annotation.RequestMapper;
import com.bauer.framework.autumn.annotation.WebController;
import com.bauer.framework.autumn.beandefination.BeanDefination;
import com.bauer.framework.autumn.context.AppContext;
import com.bauer.framework.autumn.exception.BaseRuntimeException;
import com.bauer.framework.autumn.utils.AnnotationUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author ：rui.wei
 * @Date ：Created in 16:01 2018/7/30
 * @Description：
 */
public class AnnotationMapping {

    /**
     * 缓存url对应的处理器
     */
    private Map<String, Object> handlerMappings = new HashMap<>();

    public void initMapping(AppContext appContext) {
        List<String> beanNames = appContext.getBeanFactory().getBeanNames();
        RequestMapper annotation;
        for (String name : beanNames) {
            BeanDefination beanDefination = appContext.getBeanFactory().getBeanDefination(name);
            if (beanDefination != null) {
                annotation = AnnotationUtils
                        .findAnnotationOnBean(beanDefination.getBeanClass(), RequestMapper.class);
                //bean上无注解
                if (annotation != null) {
                    String typeUrl = annotation.value();
                    if (!typeUrl.startsWith("/")) {
                        typeUrl = "/" + typeUrl;
                    }
                    List<String> methodUrls = getMethodUrls(beanDefination.getBeanClass());

                    registerHanlerMapping(typeUrl, methodUrls,
                            appContext.getBeanFactory().getBean(name));

                } else if (AnnotationUtils
                        .findAnnotationOnBean(beanDefination.getBeanClass(), WebController.class)
                        != null) {
                    List<String> methodUrls = getMethodUrls(beanDefination.getBeanClass());
                    registerHanlerMapping("", methodUrls,
                            appContext.getBeanFactory().getBean(name));
                }
            }
        }
    }

    public void registerHanlerMapping(String typePath, List<String> methodPaths, Object handler) {
        if (handler == null) {
            return;
        }

        for (String path : methodPaths) {
            if (this.handlerMappings.get(path) != null) {
                throw new BaseRuntimeException("存在重复路径信息...");
            }
            String urlPath;
            if (path.startsWith("/")) {
                urlPath = typePath + path;
            } else {
                urlPath = "/" + typePath + path;
            }

            this.handlerMappings.put(urlPath, handler);
        }
    }

    private List<String> getMethodUrls(Class handlerClass) {
        List<String> urls = new ArrayList<>();
        Method[] methods = handlerClass.getDeclaredMethods();
        for (Method method : methods) {
            RequestMapper requestMapping = AnnotationUtils
                    .findAnnotationOnMethod(method, RequestMapper.class);
            if (requestMapping == null) {
                continue;
            }

            if (!requestMapping.value().startsWith("/")) {
                urls.add("/" + requestMapping.value());
            } else {
                urls.add(requestMapping.value());
            }

        }
        return urls;
    }
}
